<?php

// 处理所有请求
function proxyRequest($url, $requestMethod, $requestHeaders, $requestBody)
{
  $targetUrl = urldecode($url);

  // 初始化 cURL 会话
  $ch = curl_init($targetUrl);

  //允许所有域（不推荐，仅用于测试）
  // header("Access-Control-Allow-Origin: *");
  // header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
  // header("Access-Control-Allow-Headers: Content-Type, Authorization");
  // 设置 cURL 选项
  curl_setopt($ch, CURLOPT_HEADER, true);
  curl_setopt($ch, CURLOPT_NOBODY, false);
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 禁用 SSL 证书验证（不推荐）
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回响应而不是直接输出

  // 根据请求方法设置 cURL 选项
  if ($requestMethod === 'POST') {
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody);
    // 如果请求体是表单数据，需要特别处理
    if (is_array($requestBody) && array_keys($requestBody)[0] === '@') {
      // 处理文件上传（这里简化处理，仅作为示例）
      foreach ($requestBody as $key => $value) {
        if (strpos($value, '@') === 0) {
          $filePath = substr($value, 1);
          $cfile = new CURLFile($filePath, mime_content_type($filePath), basename($filePath));
          unset($requestBody[$key]);
          $requestBody[$key] = $cfile;
        }
      }
      curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($requestBody));
    } else {
      curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge($requestHeaders, ['Content-Type: application/json']));
      curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($requestBody));
    }
  } else {
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $requestMethod);
  }
  curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge($requestHeaders, ['user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0']));

  // 设置 URL（确保是完整的 URL）
  $parsedUrl = parse_url($targetUrl);
  if (!isset($parsedUrl['scheme'])) {
    $targetUrl = 'http://' . $targetUrl; // 默认使用 HTTP 协议
  }
  curl_setopt($ch, CURLOPT_URL, $targetUrl);

  // 执行请求并获取响应
  $response = curl_exec($ch);

  // 获取响应头和状态码
  $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  $responseHeaders = substr($response, 0, $headerSize);
  $responseBody = substr($response, $headerSize);
  $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

  // 关闭 cURL 会话
  curl_close($ch);

  // 解析响应头
  $responseHeaderArray = [];
  foreach (explode("\r\n", $responseHeaders) as $headerLine) {
    if (strpos($headerLine, ':') !== false) {
      list($key, $value) = explode(':', $headerLine, 2);
      $responseHeaderArray[trim($key)] = trim($value);
    }
  }

  // 设置响应头并发送响应数据
  foreach ($responseHeaderArray as $key => $value) {
    header("$key: $value");
  }
  http_response_code($statusCode);

  $f = false;  //  false = true;
  if ($f) {
    echo $targetUrl;
    echo '<br/>';
    echo $requestMethod;
    echo '<br/>';
    echo $response;
    echo '<br/>';
    echo $statusCode;
    echo '<br/>';
    echo $headerSize;
    echo '<br/>';
    echo json_encode($responseHeaders);
  } else {
    echo $responseBody;
  }
}

// 处理请求
$url = isset($_GET['url']) ? $_GET['url'] : '';
// $url = $_SERVER['REQUEST_URI'];
$requestMethod = $_SERVER['REQUEST_METHOD'];
$requestHeaders = getallheaders();

// 没有需要转发请求的话，直接重定向到首页。
if (!$url) {
  header("location:/public/index.html");
  return;
}

// 处理 POST 请求的 body
$requestBody = file_get_contents('php://input');
if ($requestMethod === 'POST' && !empty($requestBody)) {
  parse_str($requestBody, $parsedBody);
  // 如果是 JSON 格式，则解析 JSON
  if (isset($requestHeaders['Content-Type']) && strpos($requestHeaders['Content-Type'], 'application/json') !== false) {
    $parsedBody = json_decode($requestBody, true);
  }
  $requestBody = $parsedBody;
} else {
  $requestBody = [];
}

$f = false;  //  false = true;
if ($f) {
  echo urldecode($url);
  echo '<br/>';
  echo $requestMethod;
  echo '<br/>';
  echo json_encode($requestHeaders);
  echo '<br/>';
  echo json_encode($requestBody);
}

// 代理请求
proxyRequest($url, $requestMethod, $requestHeaders, $requestBody);

?>